# 创建时间:2023/2/9 22:49
# 创建人:天霄
# 计划 :SenjoTwintail
# 文件 :CommonElement.py
# 基于 Python 3.8.2
# ========================================
# 公共元素
# ========================================
import first
from typing import Union
import pygame
from pygame.sprite import Sprite
from pygame.surface import Surface, SurfaceType


class SpriteCommon(Sprite):
    """通用精灵"""

    def __init__(self, image, cut_rect=None, angle=0, scale=None, clickRect: pygame.Rect = None):
        """剪切后生成一个精灵

        :param image: 图片路径/图片对象
        :param cut_rect: 切割原图片的坐标(x,y,w,h)
        :param angle: 逆时针旋转角度
        :param scale: 图片缩放倍数
        :param clickRect: 可点击区域(x,y,w,h)
        """
        super().__init__()
        self.image = image if image is Surface else pygame.image.load(image).convert_alpha()
        if cut_rect is not None:
            self.image = self.image.subsurface(cut_rect)
        if scale is not None:
            self.image = pygame.transform.rotozoom(self.image, angle, scale)
        self.rect = self.image.get_rect()
        self.rect.topleft = (0, 0)
        self.clickRect = clickRect

    def change(self, surface):
        """变更图片"""
        setattr(self, 'image', surface)
        return self

    def resize(self, size):
        """重设图片尺寸"""
        self.image = pygame.transform.scale(self.image, size)
        return self

    def draw_in(self, surface, rect):
        """在图像上继续画一个图像"""
        self.image.blit(surface, rect)

    def draw_in_center(self, surface: Surface):
        """在图像中心位置继续画一个图像"""
        rect = surface.get_rect()
        rect.center = self.image.get_rect().center
        self.image.blit(surface, rect)

    def clickable(self, x, y):
        """判断当前坐标是否在可点击区域"""
        if self.clickRect is None:
            return None
        return self.clickRect.collidepoint(x, y)


class SpriteSoldier(Sprite):
    """精灵：元帅、军士"""

    def __init__(self, code, image, imgtype, scale=None):
        """剪切后生成一个精灵

        :param code: 军士代码
        :param image: 图片路径/图片对象
        :param imgtype: 图片类型（full-全身，half-半身，head-头像，face-脸）
        :param scale: 图片缩放倍数
        """
        if imgtype not in ('full', 'half', 'head', 'face'):
            raise KeyError(f'图片类型“{imgtype}”不存在！')
        super().__init__()
        self.code = code
        self.imgtype = imgtype
        self.image = image if image is Surface else pygame.image.load(image).convert_alpha()
        if scale is not None:
            self.image = pygame.transform.rotozoom(self.image, 0, scale)
        self.rect = self.image.get_rect()
        self.rect.topleft = (0, 0)
        self.headRect = None
        self.oppaiRect = None
        if self.imgtype == 'half':
            self.headRect = pygame.Rect(133, 33, 290, 237)
            self.oppaiRect = pygame.Rect(191, 316, 243, 130)

    def change(self, surface):
        """变更图片"""
        setattr(self, 'image', surface)
        return self

    def resize(self, size):
        """重设图片尺寸"""
        self.image = pygame.transform.scale(self.image, size)
        return self

    def touchWhere(self, x, y):
        """判断坐标在哪个区域"""
        if self.imgtype != 'half':
            return None
        if self.headRect.collidepoint(x, y):
            return 'head'
        if self.oppaiRect.collidepoint(x, y):
            return 'oppai'
        return 'others'


class PageDict:
    """页面管理"""

    def __init__(self, bgsurface: Union[Surface, SurfaceType]):
        """页面管理

        :param bgsurface: 背景图对象
        """
        self.screen = first.screen
        self.bg = bgsurface
        self.SurfaceDict = {'bg': self.bg}
        '''所有图像对象（不定类型，也可能为精灵）'''
        self._key_number = 1
        self.screen_size = pygame.display.get_window_size()
        self.screen_sizeRect = pygame.Rect(0, 0, *self.screen_size)

    def __del__(self):
        """销毁"""
        del self.SurfaceDict
        del self._key_number
        del self.bg

    def add(self, surface, key=None):
        """添加图片

        :param surface: 图片对象
        :param key: 为图片设置唯一值以进行索引，若重复则抛错
        :return: 该图片的key
        """
        if key in self.SurfaceDict:
            raise KeyError(f'键”{key}“已存在！当前键：{self.SurfaceDict.keys()}')
        elif key is None:
            self._key_number += 1
            key = '_'.join(['key', str(self._key_number)])
        self.SurfaceDict[key] = surface
        return key

    def remove(self, key):
        """移除图片"""
        if key not in self.SurfaceDict:
            raise KeyError(f'键”{key}“不存在！当前键：{self.SurfaceDict.keys()}')
        self.SurfaceDict.pop(key)
        self._key_number -= 1

    def set(self, key, surface):
        """替换图片"""
        self.SurfaceDict[key] = surface
        return surface

    def clear(self):
        """清空图片"""
        self.SurfaceDict.clear()
        self.SurfaceDict = {'bg': self.bg}
        self._key_number = 1

    def get(self, key):
        """获取图片"""
        if key not in self.SurfaceDict:
            raise KeyError(f'键”{key}“不存在！当前键：{self.SurfaceDict.keys()}')
        surface: Union[Surface, SurfaceType]
        surface = self.SurfaceDict[key]
        return surface

    def draw(self, key, dest, area=None):
        """绘制图片"""
        if key not in self.SurfaceDict:
            raise KeyError(f'键”{key}“不存在！当前键：{self.SurfaceDict.keys()}')
        surface = self.get(key)
        self.screen.blit(surface, dest, area)

    def drawAll(self):
        """绘制所有"""
        self.screen.blit(self.bg, (0, 0))
